﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConferenceRegister.Domain
{
    public class RegisterService : IDisposable
    {
        public Context All = new Context();

        public bool IsPublicRegistrationClosed(int conferenceID)
        {
            List<Seat> s = All.Seats.All.Where(e => e.ConferenceID == conferenceID && !e.IsTardy).ToList();
            if (s.Count == 0) return true;
            else return DateTime.Now > s.Max(e => e.CloseDate).AddDays(1);
        }

        public bool IsPrivateRegistrationClosed(int conferenceID)
        {
            List<Seat> s = All.Seats.All.Where(e => e.ConferenceID == conferenceID).ToList();
            if (s.Count == 0) return true;
            else return DateTime.Now > s.Max(e => e.CloseDate).AddDays(1);
        }

        public bool IsDuplicate(Register r)
        {
            bool dup = All.Registrants.All.Where(e => e.ConferenceID == r.ConferenceID && r.FirstName.Trim().ToLower() == e.FirstName.Trim().ToLower() && r.LastName.Trim().ToLower()==e.LastName.Trim().ToLower() && r.Zip == e.Zip).Any();
            return dup;
        }

        public Conference LatestConference()
        {
            DateTime max = All.Conferences.All.Max(e=>e.EndDate);
            return All.Conferences.Find(e => e.EndDate == max); 
        }

        public List<Register> Registrants(int conferenceID)
        {
            return All.Registrants.Filter(e => e.ConferenceID == conferenceID).ToList();
        }

        public List<vSeat> Seats(int conferenceID)
        {
            return All.vSeats.Filter(e => e.ConferenceID == conferenceID).ToList();
        }


        /// <summary>
        /// Finds the first empty seat available in the conference.  If there is no empty seat available, it returns null
        /// </summary>
        public vSeat AvailableSeat(int conferenceID)
        {
            List<vSeat> seats = Seats(conferenceID);
            Conference c = All.Conferences.Find(conferenceID);
            if (c == null) return null;
            if (c.IsStrictSeating)
                return seats.OrderBy(e => e.CloseDate).Where(e => !e.IsFull).FirstOrDefault();
            else
                return seats.Sum(e=>e.ActualSeats) > seats.Sum(e=>e.Capacity) ? null : seats.OrderBy(e => e.CloseDate).Where(e => DateTime.Today < e.CloseDate).FirstOrDefault();
        }

        /// <summary>
        /// Finds the first empty ministry slot available for the specified ministry.  If there is no empty slot available, it returns null
        /// </summary>
        public MinistrySignup AvailableMinistrySlot(int ministryID)
        {
            vMinistry m = All.vMinistries.Find(ministryID);
            if (m.IsFull) return null;
            return new MinistrySignup { MinistryID = ministryID, Day = m.OpenDay, Timeslot = m.OpenTimeslot, Room = m.OpenRoom };
        }

        public List<vMinistry> AvailableMinistries()
        {
            return All.vMinistries.Filter(e => !e.IsFull).ToList();
        }

        public int UnpaidDays(Register r, Conference c=null)
        {
            if (r.Conference == null && c != null && c.ID == r.ConferenceID) r.Conference = c;
            double daysUnpaid = (r.PaymentAmount >= r.Conference.Cost ? (r.PaymentDate.Value-DateTime.Now).TotalDays : (DateTime.Now-r.SubmitDate).TotalDays);
            return (int)Math.Round(daysUnpaid);
        }

        public void Dispose() { All.Dispose(); }
    }
}
